import { createAsyncThunk, createSlice, isRejected } from "@reduxjs/toolkit";
import { getRequest } from "../util/Net";
import { RootState } from "./store";

// 1. Requests.

interface LoginRequest {
  userName: string;
  password: string;
}

// 2. Responses.

interface LoginResponse {
  token: string;
  authorities: string[];
}

// 3. Params for reducers.

interface LoginParams {
  userName: string;
  password: string;
}

// 4. State and initial value definition.

interface AuthState {
  loggedIn: boolean;
  loadFailed: boolean;
  token: string;
  authorities: string[];
}

const initialState: AuthState = {
  loggedIn: false,
  loadFailed: false,
  token: '',
  authorities: []
};

// 5. Async functions definition.

const login = createAsyncThunk('api/login', async (params: LoginParams) => {
  const response = await getRequest<LoginResponse, LoginRequest>({
    url: '/account',
    params: {
      userName: params.userName,
      password: params.password
    },
    withToken: false
  });
  return response.data;
});

// 6. Slice definition.

const authSlice = createSlice({
  name: 'auth',
  initialState: initialState,
  reducers: {
    clear: (state) => {
      state.loggedIn = false;
      state.token = '';
      state.authorities = [];
      localStorage.removeItem('token');
      localStorage.removeItem('authorities');
    },
    load: (state) => {
      const token = localStorage.getItem('token');
      const authorityString = localStorage.getItem('authorities');
      if (token !== null && authorityString !== null) {
        state.token = token;
        state.authorities = authorityString.split(',');
        state.loggedIn = true;
      }
    }
  },
  extraReducers: (builder) => {
    builder.addCase(login.fulfilled, (state, action) => {
      const data = action.payload.result;
      state.loggedIn = true;
      state.token = data.token;
      state.authorities = data.authorities;
      localStorage.setItem('token', data.token);
      localStorage.setItem('authorities', data.authorities.join(','));
    }).addMatcher(isRejected, (state, action) => {
      console.log(action.error);
    });
  }
});

export default authSlice.reducer;
export const authActions = {...authSlice.actions, login};
export const selectLoggedIn = (root: RootState) => root.authReducer.loggedIn;
export const selectAuthLoadFailed = (root: RootState) => root.authReducer.loadFailed;
export const selectToken = (root: RootState) => root.authReducer.token;
export const selectAuthorities = (root: RootState) => root.authReducer.authorities;